package com.dcy.daily.skill.java.lambda;

/**
 * 内部类、lambda表达式、方法引用练习，对Java应官教程中Questions and Exercises章节
 */
public class DataStructure {
    
    // Create an array
    private final static int SIZE = 15;
    private int[] arrayOfInts = new int[SIZE];
    
    public DataStructure() {
        // fill the array with ascending integer values
        for (int i = 0; i < SIZE; i++) {
            arrayOfInts[i] = i;
        }
    }
    
    public void printEven() {
        
        // Print out values of even indices of the array
        DataStructureIterator iterator = this.new EvenIterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
    }
    
    interface DataStructureIterator extends java.util.Iterator<Integer> { } 

    // Inner class implements the DataStructureIterator interface,
    // which extends the Iterator<Integer> interface
    
    private class EvenIterator implements DataStructureIterator {
        
        // Start stepping through the array from the beginning
        private int nextIndex = 0;
        
        public boolean hasNext() {
            
            // Check if the current element is the last in the array
            return (nextIndex <= SIZE - 1);
        }        
        
        public Integer next() {
            
            // Record a value of an even index of the array
            Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
            
            // Get the next even element
            nextIndex += 2;
            return retValue;
        }
    }

    /**
     * Define a method named print(DataStructureIterator iterator).
     * Invoke this method with an instance of the class EvenIterator
     * so that it performs the same function as the method printEven.
     * @param iterator
     */
    public void print(DataStructureIterator iterator){
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
    }

    /**
     * Define a method named print(java.util.function.Function<Integer, Boolean> iterator) that performs the same
     * function as print(DataStructureIterator iterator).
     * Invoke this method with a lambda expression to print elements that have an even index value.
     * Invoke this method again with a lambda expression to print elements that have an odd index value.
     * @param iterator
     */
    public void print(java.util.function.Function<Integer, Boolean> iterator){
        for (int i = 0; i < this.arrayOfInts.length; i++) {
            if(iterator.apply(i)){
                System.out.print(this.arrayOfInts[i] + " ");
            }
        }
        System.out.println();
    }

    /**
     * Define two methods so that the following two statements print elements
     * that have an even index value and elements that have an odd index value:
     * @param i
     * @return
     */
    public static boolean isEvenIndex(Integer i){
        return i%2==0;
    }


    /**
     * Define two methods so that the following two statements print elements
     * that have an even index value and elements that have an odd index value:
     * @param i
     * @return
     */
    public static boolean isOddIndex(Integer i){
        return i%2!=0;
    }

    public static void main(String s[]) {
        // Fill the array with integer values and print out only
        // values of even indices
        DataStructure ds = new DataStructure();

        //exercises one
        EvenIterator iterator = ds.new EvenIterator();
        ds.print(iterator);

        //exercises two
        ds.print(new DataStructureIterator() {
            private int nextIndex = 1;

            @Override
            public boolean hasNext() {
                return (nextIndex <= SIZE - 1);
            }

            @Override
            public Integer next() {
                Integer retValue = Integer.valueOf(ds.arrayOfInts[nextIndex]);
                nextIndex += 2;
                return retValue;
            }
        });

        //exercises three
        ds.print(i -> i%2==0 );
        ds.print(i -> i%2!=0 );

        //exercises four
        ds.print(i -> DataStructure.isEvenIndex(i));
        ds.print(i -> DataStructure.isOddIndex(i));
        ds.print(DataStructure::isEvenIndex);
        ds.print(DataStructure::isOddIndex);
    }
}